package com.arcsoft.commonbase.base

import androidx.core.net.ParseException
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.arcsoft.commonbase.bus.Bus
import com.arcsoft.commonbase.bus.bus_finish_load
import com.arcsoft.commonbase.bus.bus_logout
import com.arcsoft.commonbase.ext.customShowLong
import com.arcsoft.commonbase.net.ApiException
import com.blankj.utilcode.util.ActivityUtils
import com.google.gson.JsonParseException
import kotlinx.coroutines.CancellationException
import kotlinx.coroutines.Deferred
import kotlinx.coroutines.Job
import kotlinx.coroutines.async
import kotlinx.coroutines.launch
import org.json.JSONException
import retrofit2.HttpException
import java.net.ConnectException
import java.net.SocketException
import java.net.SocketTimeoutException
import java.net.UnknownHostException

typealias Block<T> = suspend () -> T
typealias Error = suspend (e: Exception) -> Unit
typealias Cancel = suspend (e: Exception) -> Unit

open class BaseViewModel : ViewModel() {

    val isShowLoading = MutableLiveData<Boolean>()

    //你只能在suspend修饰的方法中调用suspend方法，
    // 或者使用launch关键字来启动一个新的协程来调用suspend方法。
    fun launch(
        block: Block<Unit>,
        isShowDialog: Boolean = true,
        error: Error? = null,
        cancel: Cancel? = null
    ): Job {

//        if (isShowDialog) isShowLoading.value = true


        return viewModelScope.launch {
            val topActivity = ActivityUtils.getTopActivity()
            if (isShowDialog) {
                if (topActivity is BaseBindingActivity<*>) {
                    topActivity.showLoading()
                }
            }
            try {
                block.invoke()
            } catch (e: Exception) {
                when (e) {
                    is CancellationException -> {
                        cancel?.invoke(e)
                    }

                    else -> {
                        onError(e, error == null)
                        error?.invoke(e)
                    }
                }
            }

            if (topActivity is BaseBindingActivity<*>) {
                topActivity.dismissLoading()
            }

            Bus.post(bus_finish_load, "")
//            isShowLoading.value = false
        }
    }

    /**
     * 创建并执行协程
     * @param block 协程中执行
     * @return Deferred<T>
     */
    protected fun <T> async(block: Block<T>): Deferred<T> {
        return viewModelScope.async { block.invoke() }
    }

    private fun onError(e: Exception, isShowToast: Boolean = true) {
        print(e.printStackTrace())
        when (e) {
            is ApiException -> {
                if (isShowToast) {
                    customShowLong(e.message)
                }
                if (e.msgCode == "401001") {
                    Bus.post(bus_logout, "")
                }
            }

            is HttpException -> {
                customShowLong(e.message)
            }
            //链接失败
            is ConnectException, is SocketException, is UnknownHostException -> {
                customShowLong("网络链接失败")
            }
            //链接超时
            is SocketTimeoutException -> {
                customShowLong("网络请求超时")
            }
            // 数据解析错误
            is JsonParseException, is JSONException, is ParseException -> {
                customShowLong("数据解析错误")
            }

            is NumberFormatException -> {
                customShowLong("格式化错误")
            }
            // 其他错误
            else -> {
                e.message?.let { customShowLong(it) }
            }
        }
    }

}